package com.xinqi.modules.sys.sensitive.word.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xinqi.common.base.enums.YesNoEnum;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.common.mybatis.utils.Queries;
import com.xinqi.modules.sys.sensitive.word.component.SensitiveWordSubjectManager;
import com.xinqi.modules.sys.sensitive.word.convert.SensitiveWordConvert;
import com.xinqi.modules.sys.sensitive.word.domain.SensitiveWordEntity;
import com.xinqi.modules.sys.sensitive.word.dto.req.SensitiveWordCreateDTO;
import com.xinqi.modules.sys.sensitive.word.dto.req.SensitiveWordDeleteDTO;
import com.xinqi.modules.sys.sensitive.word.dto.req.SensitiveWordQueryDTO;
import com.xinqi.modules.sys.sensitive.word.dto.req.SensitiveWordUpdateDTO;
import com.xinqi.modules.sys.sensitive.word.dto.rsp.SensitiveWordResultDTO;
import com.xinqi.modules.sys.sensitive.word.manager.SensitiveWordManager;
import com.xinqi.modules.sys.sensitive.word.service.SensitiveWordService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.validation.Valid;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 敏感词管理表服务层实现
 *
 * @author: wenjie
 * @date: 2023/08/02
 */
@Validated
@Service("sensitiveWordService")
@RequiredArgsConstructor
public class SensitiveWordServiceImpl implements SensitiveWordService {
    private final SensitiveWordConvert sensitiveWordConvert;
    private final SensitiveWordManager sensitiveWordManager;

    @Lazy
    private final SensitiveWordSubjectManager sensitiveWordSubjectManager;

    /**
     * 分页查询 敏感词管理表数据
     */
    @Override
    @DS("slaver")
    public PageInfo<SensitiveWordResultDTO> page(Param pageable, SensitiveWordQueryDTO query) {
        IPage<SensitiveWordEntity> page = sensitiveWordManager.page(Pages.page(pageable), wrapper(query));
        return Pages.convert(page, sensitiveWordConvert::convert);
    }

    /**
     * 查询 敏感词管理表数据
     */
    @Override
    public List<SensitiveWordResultDTO> find(SensitiveWordQueryDTO query) {
        return sensitiveWordManager.list(wrapper(query)).stream()
            .map(sensitiveWordConvert::convert).collect(Collectors.toList());
    }

    private LambdaQueryWrapper<SensitiveWordEntity> wrapper(SensitiveWordQueryDTO query) {
        LambdaQueryWrapper<SensitiveWordEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(SensitiveWordEntity::getId, v));
        Queries.accept(query.getType(), v -> wrapper.eq(SensitiveWordEntity::getType, v));
        Queries.accept(query.getStatus(), v -> wrapper.eq(SensitiveWordEntity::getStatus, v));
        return wrapper;
    }

    /**
     * 根据id查询 敏感词管理表数据
     */
    @Override
    public SensitiveWordResultDTO findById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return Optional.ofNullable(sensitiveWordManager.findById(id)).map(sensitiveWordConvert::convert).orElse(null);
    }

    /**
     * 新增 敏感词管理表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insert(@Valid SensitiveWordCreateDTO dto) {
        Set<String> types = this.findTypes();
        CommonErrors.BAD_REQUEST.check(!types.contains(dto.getType()), "分类已存在");

        SensitiveWordEntity entity = sensitiveWordConvert.create(dto);
        entity.setQuantity(Long.parseLong(String.valueOf(dto.getContent().split(",").length)));
        sensitiveWordManager.save(entity);

        //通知
        sensitiveWordSubjectManager.notifyOnCreate(entity);

        return entity.getId();
    }

    /**
     * 根据id修改 敏感词管理表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateById(@Valid SensitiveWordUpdateDTO dto) {
        SensitiveWordEntity old = Optional.ofNullable(sensitiveWordManager.getById(dto.getId()))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("数据不存在"));

        CommonErrors.BAD_REQUEST.check(checkTypes(dto, old), "分类已存在");

        SensitiveWordEntity entity = sensitiveWordConvert.update(dto);
        entity.setQuantity(Long.parseLong(String.valueOf(dto.getContent().split(",").length)));
        Boolean bo = sensitiveWordManager.updateById(entity);

        //通知
        sensitiveWordSubjectManager.notifyOnUpdate(entity);

        return bo;
    }

    private Boolean checkTypes(SensitiveWordUpdateDTO dto, SensitiveWordEntity old) {
        Set<String> types = this.findTypes();
        return !types.contains(dto.getType()) || Objects.equals(dto.getType(), old.getType());
    }

    /**
     * 根据id删除 敏感词管理表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        SensitiveWordEntity old = Optional.ofNullable(sensitiveWordManager.getById(id))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("数据不存在"));

        Boolean bo = sensitiveWordManager.deleteById(id);

        //通知
        sensitiveWordSubjectManager.notifyOnDelete(old);

        return bo;
    }

    /**
     * 根据id删除 敏感词管理表数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(SensitiveWordDeleteDTO dto) {
        return deleteById(dto.getId());
    }

    @Override
    public Set<String> findTypes() {
        return sensitiveWordManager.findTypes();
    }

    /**
     * 后台不要调用这个接口，后台使用 DictionarySensitiveDataLoader.getValue(String key)
     *
     * @param type
     * @return
     */
    @Override
    public SensitiveWordResultDTO findByTypeAndStatus(String type, Integer status) {
        CommonErrors.BAD_REQUEST.check(StringUtils.isNotEmpty(type) && Objects.nonNull(status), "类型和状态均不能为空");
        SensitiveWordQueryDTO query = new SensitiveWordQueryDTO();
        query.setType(type);
        query.setStatus(status);
        return Optional.ofNullable(sensitiveWordManager.getOne(wrapper(query))).map(sensitiveWordConvert::convert).orElse(null);
    }

    @Override
    public List<SensitiveWordResultDTO> listEffective() {
        SensitiveWordQueryDTO queryDTO = new SensitiveWordQueryDTO();
        queryDTO.setStatus(YesNoEnum.YES.ordinal());
        return sensitiveWordManager.list(wrapper(queryDTO)).stream().map(sensitiveWordConvert::convert).collect(Collectors.toList());
    }

}
